<?php
/** 
*
* @package phpBB3 :: phpBB OpenID
* @version $Id: openid_class.php 77 2010-02-28 07:37:17Z jonzenor $
* @copyright (c) 2007 phpBB Group 
* @license http://opensource.org/licenses/gpl-license.php GNU Public License 
* @author: MasterZ - http://www.phpbb.com/community/memberlist.php?mode=viewprofile&u=83328
*
*/

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
} 

class phpbb_openid {
	
	private $trust_root = "";
	private $return_url = "";
	
	function getTrustRoot()
	{
		return $this->trust_root;
	}
	
	function getReturnURL()
	{
		return $this->return_url;
	}
	
	function setup_url($page = 'login')
	{
		$protocol = 'http';
		if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on")
		{
			$protocol .= 's';
		}
		
		// Get the port number
		if ($_SERVER['SERVER_PORT'] == "80")
		{
			$port = "";
		}
		else
		{
			$port = ":" . $_SERVER['SERVER_PORT'];
		}
		
		// Get webroot
		if ($_SERVER['PHP_SELF'] == "/")
		{
			$webRoot = "";
		}
		else
		{
			$webRoot = dirname($_SERVER['PHP_SELF']);
		}
		
		switch($page)
		{
			case 'ucp':
				global $ucp_i;
				$use_page = '/ucp.php?i=phpbb_openid&mode=view&authopenid=yes';
			break;
			case 'login':
			default:

				$use_page = "/openid_login.php?server_auth=1";
				
			break;
		}
		
		// Create the return url
		$this->return_url = sprintf("$protocol://%s%s%s" . $use_page, $_SERVER['SERVER_NAME'], $port, $webRoot);
		// if (OID_DEBUG) { echo "Return URL = " . $this->return_url . "<br />"; }

		$this->trust_root = sprintf("$protocol://%s%s%s", $_SERVER['SERVER_NAME'], $port, $webRoot);
		// if (OID_DEBUG) { echo "Trust Root = " . $this->trust_root . "<br /><br />"; }
	}
	
	function processOID($auth_req = "")
	{
		if (!$auth_req)
		{
			global $auth_request;
			$auth_req = $auth_request;
		}
		
		$redirect_url = $auth_req->redirectURL($this->trust_root, $this->return_url);
		$this->redirect($redirect_url);
	}
	
	function redirect($url)
	{
		header("Location: ". $url);
		// this is phpBB's way to do it, need to figure out how to make it work instead of header
		// redirect($url, false, true);
		// echo "<a href='" . $url . "'>Redirecting...</a><br /><br />" . $url;
	}
	
	function cleanOidURL($openid)
	{
		return strtolower($openid);
	}
	
	function findOpenID($openid)
	{
		global $db;
		
		// See if the OpenID is already registered
		$sql = "SELECT * FROM " . OPENID_URLS_TABLE . "
			WHERE openid_url = '$openid' OR openid_clean_url = '" . $this->cleanOidURL($openid) . "'";
		
		$result = $db->sql_query($sql);
		if (!$result)
		{
			// Query failed
			trigger_error($user->lang['OPENID_ERROR_DB_FAIL'] . ' ' . $sql);
		}
		
		// get result...if user exists, return user_id, if not, return 0.
		return ($row = $db->sql_fetchrow($result)) ? $row['user_id'] : 0;
	}

	function setSessionVar($key, $value)
	{
		global $user;
		// Need to get rid of $_SESSION after we figure out how to change it in the openid library
		$_SESSION[$key] = $value;
		// $user->set_cookie($key, $value, 0);
	}
	
	function getSessionVar($key)
	{
		// return request_var($key, "", true, true);
		return $_SESSION[$key];
	}
	
	function usernameFromOpenID($openid)
	{
		// This function is from the openid2username.php file
		return toUserName($openid);
	}
	
	function usernameExists($username)
	{
		// See if a username exists
		global $db;
		$user_found = false;
		
		// Try to use SELECT COUNT() when we have time to test that it works right
		$sql = "SELECT username FROM " . USERS_TABLE . "
				WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
				
		$result = $db->sql_query($sql);
		
		if ($row = $db->sql_fetchrow($result))
		{
			$user_found = true;
		}
		
		return $user_found;
	}
	
	function createUser($username, $email, $openid)
	{
		global $db, $openid;
		$group_id = 2;
		$sql = "SELECT *
		        FROM " . GROUPS_TABLE . "
		        WHERE group_name = 'REGISTERED' ";
		if ( !($result = $db->sql_query($sql)) )
		{
		    trigger_error('OPENID_ERROR_DB_FAIL' . $sql);
		}
		if( $row = $db->sql_fetchrow($result) )
		{
		    $group_id = $row['group_id'];
		}
		
		// Generate a password
		$plain_text_password = $this->generatePass();
		
		// Setup User Data
		$user_row = array(
		    'username' => $username,
		    'user_password' => phpbb_hash($plain_text_password),
		    'user_email' => $email,
		    'group_id' => $group_id,
		    'user_timezone' => '0',
		    'user_dst' => '0',
		    'user_lang' => $config['default_lang'],
		    'user_type' => '0',
		    'user_actkey' => '',
		    'user_ip' => $_SERVER['REMOTE_ADDR'],
		    'user_inactive_reason' => '0',
		    'user_website' => $openid,
		    'user_inactive_time' => '0');
		$user_id = user_add($user_row);

		// Send PM with users password
		$this->sendPass($user_id, $plain_text_password);
		
		// Erase the password to be safe
		$plain_text_password = null;

		// add openid URL
		$sql = "INSERT INTO " . OPENID_URLS_TABLE . " SET 
			openid_url = '" . $openid . "',
			openid_clean_url = '" . $this->cleanOidURL($openid) . "',
			user_id = '" . $user_id . "'";

		if ( !($result = $db->sql_query($sql)) )
		{
		    trigger_error($user->lang['OPENDID_ERROR_DB_FAIL'] . ' ' . $sql);
		}
		else
		{
		    return $user_id;
		}
		
	}
	
	private function sendPass($user_id = 0, $password = "")
	{
		global $phpbb_root_path, $phpEx, $user, $config;
		
		// Load config settings
		include($phpbb_root_path . "includes/openid/openid_config." . $phpEx);
		
		if ($oid_config['pm_enabled'])
		{
			include($phpbb_root_path . "includes/functions_privmsgs." . $phpEx);
		
			// This function will send the generated password to the user after creating their account
			
			// Setup replacement strings
			$find_word = array("%username%", "%password%", "%from_uname%", "%email_sig%", "%server_name", "%sitename%");
			$replace_word = array("Username", $password, $oid_config['from_uname'], $config['board_email_sig'], $config['server_name'], $config['sitename']);

			// We need to load the language vars
			$user->add_lang("mods/lang_phpbb_openid");
			
			$subject = $user->lang['OPENID_MAIL_PASS_SUBJ'];
			$text = $user->lang['OPENID_MAIL_PASS_MSG'];
			
			$subject = str_replace($find_word, $replace_word, $subject);
			$text = str_replace($find_word, $replace_word, $text);
							
			$text = utf8_normalize_nfc($text);
			$subject = utf8_normalize_nfc($subject);
			
			$poll = $uid = $bitfield = $options = '';
			generate_text_for_storage($subject, $uid, $bitfield, $options, false, false, false);
			generate_text_for_storage($text, $uid, $bitfield, $options, true, true, true);
			
			$data = array(
				'address_list' => array('u' =>array($user_id => 'to')),
				'from_user_id' => $oid_config['from_uid'],
				'from_username' => $oid_config['from_uname'],
				'icon_id' => 0,
				'from_user_ip' => $user->data['user_ip'],
				'enable_bbcode' => true,
				'enable_smilies' => true,
				'enable_urls' => true,
				'enable_sig' => false,
				'message' => $text,
				'bbcode_bitfield'=> $bitfield,
				'bbcode_uid' => $uid,
			);	
			
			submit_pm('post', $subject, $data, false);
		} // End sending PM
	}
	
	private function generatePass() 
	{
		global $username;
		global $db_prefix;
		$upper = "ABCDEFGHJKLMNPQRSTUVWXYZ";
		$lower = "abcdefghjkmnpqrstuvwxyz";
		$number = "23456789";
		$special = "!@#$%^&*(){}[]";

		$max_num = 5;
		$req_num = 3;
		$max_spec = 4;
		$req_spec = 2;
		$max_upper = 5;
		$req_upper = 2;
		$max_lower = 6;
		$req_lower = 2;


		$num_chars = rand(10,14);
		$pass = "blank";

		while($pass != "good"){
			$used_num = 0;
			$used_spec = 0;
			$used_upper = 0;
			$used_lower = 0;
			$key = "";

			for($i=0; $i<$num_chars; $i++)
			{
				$check = "Ready";
				while($check != "ok")
				{
					$get_type = rand(0,3);
					if($get_type == 0)
					{
						$check = ($used_num == $max_num) ? 'redo' : 'ok';
					}
					elseif($get_type == 1)
					{
						$check = ($used_spec == $max_spec) ? 'redo' : 'ok';
					}
					elseif($get_type == 2)
					{
						$check = ($used_upper == $max_upper) ? 'redo' : 'ok';
					}
					elseif($get_type == 3)
					{
						$check = ($used_lower == $max_lower) ? 'redo' : 'ok';
					}
					else
					{
						$check = 'what happened?';
					};
				}
				if($get_type == 0)
				{
					$key .= $number{rand(0,7)};
					$used_num ++;
				}
				elseif($get_type == 1)
				{
					$key .= $special{rand(0,13)};
					$used_spec ++;
				}
				elseif($get_type == 2)
				{
					$key .= $upper{rand(0,23)};
					$used_upper ++;
				}
				elseif($get_type == 3)
				{
					$key .= $lower{rand(0,22)};
					$used_lower ++;
				}
			}
			$test = 0;
			if($used_num >= $req_num)
			{
				$test ++; 
			}
			
			if($used_spec >= $req_spec)
			{
				$test ++;
			}
			
			if($used_upper >= $req_upper)
			{
				$test ++;
			}
			
			if($used_lower >= $req_lower)
			{
				$test ++; 
			}

			$pass = ($test == 4) ? 'good' : 'try again';
		}; // END While loop

		return $key;
	}
	
	function bind($user_id, $openid)
	{
		global $db;
		$sql = "INSERT INTO " . OPENID_URLS_TABLE . " SET
			openid_url = '" . $openid. "',
			openid_clean_url = '" . $this->cleanOidURL($openid) . "',
			user_id = '" . $user_id . "'";
			
		if (!$result = $db->sql_query($sql))
		{
			trigger_error($user->lang['OPENID_ERROR_DB_FAIL'] . ' ' . $sql);
		}
	}

	function deleteOpenID($user_id, $url_id)
	{
		global $db;
		
		$sql = "DELETE FROM " . OPENID_URLS_TABLE . " WHERE id = " . $url_id . " AND user_id = " . $user_id;
		$db->sql_query($sql);
		
		return ($db->sql_affectedrows()) ? true : false;
	}
	
	function findByID($id, $user_id = 0)
	{
		global $db;

		$check_user = $user_id ? " AND user_id = '" . $user_id . "'" : "";
		
		$sql = "SELECT * FROM " . OPENID_URLS_TABLE . " WHERE
			id = '" . $id . "'" . $check_user;

		$result = $db->sql_query($sql);
		$row = $db->sql_fetchrow($result);
		$db->sql_freeresult($result);
				
		return $row['openid_url'];
	}

	function updateEmail($user_id, $email)
	{
		if (!validate_email($email))
		{
			global $db;
			
			// Email passed checks, save
			$sql = "UPDATE " . USERS_TABLE . " SET
				user_email = '" . $email . "'
				WHERE user_id = '" . $user_id . "'";
			
			$db->sql_query($sql);
		}
	}
	
}

?>